import * as THREE from 'three';
import { CSS2DRenderer } from 'three/examples/jsm/renderers/CSS2DRenderer.js';

class Base {
    constructor() {}

    destory() {
        if (!this) return;
        // console.warn('Base.destory: ', typeof this.modelsGroup, this.modelsGroup instanceof THREE.Group);
        // console.warn('Base.destory: ', this);
        Object.getOwnPropertyNames(this).forEach(k => {
            if (k === 'root') return;
            if (this[k] instanceof THREE.Scene) {
                // console.log('--scene--> ', this[k]);
                for (let i = 0, len = this[k].children.length; i < len; i++) {
                    this.deleteGroup(this[k].children[i]);
                    this[k].remove(this[k].children[i]);
                }
            } else if (this[k] instanceof THREE.Group) {
                // console.log('--group--> ', this[k]);
                this.deleteGroup(this[k]);
            } else if (this[k] instanceof THREE.Mesh) {
                // console.log('--mesh--> ', this[k]);
                this.disposeMesh(this[k]);
            } else if (this[k] instanceof THREE.WebGLRenderer || this[k] instanceof CSS2DRenderer) {
                // console.log('--renderer--> ', this[k]);
                if (typeof this[k].dispose === 'function') this[k].dispose();
                if (typeof this[k].forceContextLoss === 'function') this[k].forceContextLoss();
                this[k].domElement = null;
                this[k] = null;
            } else if (Array.isArray(this[k])) {
                // console.log('--Array--> ', this[k]);
                if (typeof this.deleteArray === 'function') this.deleteArray(this[k]);
            } else if (Object.prototype.toString.call(this[k]) === '[object Object]') {
                // console.log('--object.destory--> ', this[k], typeof this[k].destory === 'function', this[k] instanceof Base); //eslint-disable-line
                if (typeof this[k].destory === 'function') this[k].destory();
            } else {
                // console.log('--???--> ', this[k]);
                this[k] = null;
            }
            delete this[k];
        });
    }

    deleteGroup(group) {
        if (!group || !(group instanceof THREE.Group)) return;
        // console.warn('Base.deleteGroup: ', group);
        group.traverse(item => { //eslint-disable-line
            if (item instanceof THREE.Mesh) {
                this.disposeMesh(item);
            } else if (typeof item.dispose === 'function') {
                item.dispose();
            }
        });
    }

    disposeMesh(m) {
        if (m && m.geometry) m.geometry.dispose();
        if (m && m.material) m.material.dispose();
    }

    deleteArray(arr) {
        if (!arr || !arr.length) return;
        arr.forEach(a => {
            if (a instanceof THREE.Mesh) {
                this.disposeMesh(a);
            } else if (a instanceof THREE.Group) {
                this.deleteGroup(a);
            } else this.destory.call(a);
        });
    }
}

export default Base;
